﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;

namespace Medianamik.Globalization
{
    [DataContract]
    public class Resource : IEquatable<Resource>
    {
        public Resource(string id, string cultureName, string value, string resourceSet)
        {
            //ValidateParam(id, "id");
            //ValidateParam(value, "value");
            //ValidateParam(resourceSet, "resourceSet");

            if(cultureName == null)
                throw new ArgumentNullException("cultureName");

            Id = id;
            CultureName = cultureName;
            Value = value;
            ResourceSet = resourceSet;
        }

        public Resource(string id, string cultureName, string value, string resourceSet, DateTime? modifiedOn, bool localOnly)
            : this(id, cultureName, value, resourceSet)
        {
            if (cultureName == null)
                throw new ArgumentNullException("cultureName");

            Local = localOnly;

            if (modifiedOn.HasValue)
                ModifiedOn = modifiedOn;
        }

        public Resource(string id, string cultureName, string value, string resourceSet, DateTime modifiedOn)
            : this(id, cultureName, value, resourceSet)
        {
            ModifiedOn = modifiedOn;
        }
        

        [DataMember]
        public string Id
        {
            get;
            private set;

        }
        [DataMember]
        public string CultureName
        {
            get;
            private set;
        }
        [DataMember]
        public string Value
        {
            get;
            private set;
        }
        [DataMember]
        public string ResourceSet
        {
            get;
            private set;
        }
        [DataMember]
        public DateTime? ModifiedOn
        {
            get;
            private set;
        }

        [DataMember]
        public bool? Local
        {
            get;
            private set;
        }

        private static void ValidateParam(string param, string paramName)
        {
            if (param == null)
                throw new ArgumentNullException(paramName);

            if (param.Length == 0)
                throw new ArgumentException(paramName + " is empty");
        }
        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.
        ///                 </param>
        public bool Equals(Resource other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.Id, Id) && Equals(other.CultureName, CultureName) && Equals(other.ResourceSet, ResourceSet);
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. 
        ///                 </param><exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.
        ///                 </exception><filterpriority>2</filterpriority>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (Resource)) return false;
            return Equals((Resource) obj);
        }

        /// <summary>
        /// Serves as a hash function for a particular type. 
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        /// <filterpriority>2</filterpriority>
        public override int GetHashCode()
        {
            unchecked
            {
                int result = Id.GetHashCode();
                result = (result*397) ^ CultureName.GetHashCode();
                result = (result*397) ^ ResourceSet.GetHashCode();
                return result;
            }
        }
        public bool IsOlderThan(Resource resourceToCompare)
        {
            if (resourceToCompare == null)
                throw new ArgumentNullException("resourceToCompare");

            if (ModifiedOn.HasValue)
            {
                if (resourceToCompare.ModifiedOn.HasValue)
                    return ModifiedOn.Value < resourceToCompare.ModifiedOn.Value;
                return false;
            }
            return resourceToCompare.ModifiedOn.HasValue;
        }
    }
}
